﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using Rung.Net.Enums;
using System.IO;

namespace Rung.Net
{
    public static class NetUtility
    {
        public static int ParsePort(string s)
        {
            return int.Parse(s);
        }
        public static bool TryParsePort(string s, out int port)
        {
            try
            {
                port = ParsePort(s);
                return true;
            }
            catch
            {
                port = 0;
                return false;
            }
        }

        public static List<IPAddress> GetLocalIpV4()
        {
            List<IPAddress> result = new List<IPAddress>();
            IPAddress[] ipas = Dns.GetHostAddresses(Dns.GetHostName());

            foreach (var ipa in ipas)
            {
                if (ipa.AddressFamily == AddressFamily.InterNetwork)
                    result.Add(ipa);
            }

            return result;
        }

        #region Text
        public static string C(byte[] data)
        {
            return Encoding.Unicode.GetString(data);
        }
        public static byte[] C(string data)
        {
            return Encoding.Unicode.GetBytes(data);
        }

        /// <summary>
        /// 将源数组全部复制到目标数组的指定位置。
        /// </summary>
        /// <param name="src">源数组</param>
        /// <param name="dst">目标数组</param>
        /// <param name="dstOffset">复制到目标数组的起始位置</param>
        public static void BlockCopy(byte[] src, byte[] dst, int dstOffset)
        {
            System.Buffer.BlockCopy(src, 0, dst, dstOffset, src.Length);
        }
        #endregion

        #region Message
        /// <summary>
        /// 根据消息的类型和主体构造一个完整的消息。
        /// </summary>
        public static string GetFullMessage(int type, string message)
        {
            return string.Format("{0}{1}{2}", type, LevelSeperators.Level0, message);
        }

        /// <summary>
        /// 从接受的完整消息中分析消息的类型。
        /// </summary>
        public static int GetMessageType(string fullMessage)
        {
            int index = fullMessage.IndexOf(LevelSeperators.Level0);
            string strType = fullMessage.Substring(0, index);
            int type;

            if (int.TryParse(strType, out type))
                return type;
            else
                return MessageTypeBase.Unknow;
        }

        /// <summary>
        /// 从接受的完整消息中分析消息的主体。
        /// </summary>
        public static string GetMessageBody(string fullMessage)
        {
            int index = fullMessage.IndexOf(LevelSeperators.Level0);
            return fullMessage.Substring(index + 1);
        }
        #endregion

        #region Ping
        public static bool Ping(string host, int port)
        {
            return Ping(host, port, TimeSpan.MaxValue);
        }
        public static bool Ping(string host, int port, out TimeSpan elapsed)
        {
            return Ping(host, port, TimeSpan.MaxValue, out elapsed);
        }
        public static bool Ping(string host, int port, TimeSpan timeout)
        {
            TimeSpan elapsed;
            return Ping(host, port, timeout, out elapsed);
        }
        public static bool Ping(string host, int port, TimeSpan timeout, out TimeSpan elapsed)
        {
            using (TcpClient tcp = new TcpClient())
            {
                DateTime start = DateTime.Now;
                IAsyncResult result = tcp.BeginConnect(host, port, null, null);
                WaitHandle wait = result.AsyncWaitHandle;
                bool ok = true;

                try
                {
                    if (!result.AsyncWaitHandle.WaitOne(timeout, false))
                    {
                        tcp.Close();
                        ok = false;
                    }

                    tcp.EndConnect(result);
                }
                catch
                {
                    ok = false;
                }
                finally
                {
                    wait.Close();
                }

                DateTime stop = DateTime.Now;
                elapsed = stop.Subtract(start);
                return ok;
            }
        } 
        #endregion

        #region File
        /// <summary>
        /// 创建并返回一个新的临时文件。
        /// </summary>
        /// <param name="fileLength">文件长度</param>
        public static FileInfo GetNewTempFile(long fileLength)
        {
            string file = Path.Combine(GetTempFolder(), Guid.NewGuid().ToString("N") + ".dat");
            while (File.Exists(file))
            {
                file = Path.Combine(GetTempFolder(), Guid.NewGuid().ToString("N") + ".dat");
            }
            FileInfo fi = new FileInfo(file);
            using (FileStream fs = fi.OpenWrite())
            {
                while (fs.Position < fileLength)
                    fs.WriteByte(0);
            }
            return fi;
        }

        /// <summary>
        /// 获取用户保存的信息文件夹。
        /// </summary>
        public static string GetTempFolder()
        {
            //return System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "\\Rung.eBook");
            return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp");
        }

        /// <summary>
        /// 获取用户保存的信息文件夹。
        /// </summary>
        public static string GetTempFileName(string fileName)
        {
            return System.IO.Path.Combine(GetTempFolder(), fileName);
        }

        private static object OBJ_Log = new object();
        public static void Log(string file, string data)
        {
            lock (OBJ_Log)
            {
                File.AppendAllText(NetUtility.GetTempFileName(file), data);
            }
        }
        #endregion
    }
}
